﻿#ifndef OBJPARSE_H
#define OBJPARSE_H

#include <QString>
#include <QVector>
#include <QVector2D>
#include <QVector3D>
#include <QFile>
#include <Qt3DRender/QGeometryRenderer>
#include <Qt3DRender/QBuffer>
#include <Qt3DRender/QAttribute>
#include <Qt3DRender/QGeometry>
#include <QPhongMaterial>
#include <QObject>

#include "objheader.h"

// 模型文件解析
class ModelFileParse
        :public QObject
{
    Q_OBJECT;
public:

signals:

    /**
     * @brief parseModelFileStart 模型开始解析
     */
    void parseModelFileStart();

    /**
     * @brief parseModelFileDoing 模型正在解析
     * @param currentMainProcessNum 模型解析主进度
     * @param currentSecondaryProgressNum 模型解析次进度，0~100
     * @param message 解析消息，当前正在解析哪一部分
     */
    void parseModelFileDoing(int currentMainProcessNum, int currentSecondaryProgressNum,const QString &message);

    /**
     * @brief parseModelFileCompleted 解析完成
     */
    void parseModelFileCompleted();

    /**
     * @brief parseModelFileError 模型解析失败
     * @param type 失败类型，0=未知错误，1=OBJ文件不存在或无法打开，2=OBJ文件解析失败，
     * 3=MTL文件不存在或无法打开，4=MTL文件解析失败
     * @param message 失败信息
     */
    void parseModelFileError(int type,const QString &message);



public:
    ModelFileParse(QObject *parent=nullptr);

    /**
     * @brief parseObjFile 解析OBJ文件
     * @param objFilePath obj文件路径
     * @param mtlFilePath mtl文件路径
     * @return 是否解析成功
     */
    bool parseModelFile(const QString &objFilePath,const QString &mtlFilePath);

    /**
     * @brief handleFace 处理面信息
     * @return
     */
    bool handleFace();

    /**
     * @brief createGeometryRenderer 從解析的數據創建幾何體渲染器
     * @return 返回配置好的QGeometryRenderer对象
     */
    Qt3DRender::QGeometryRenderer* createGeometryRenderer(QObject* parent);

    /**
     * @brief getModelCenter 获取模型中心点坐标
     * @return
     */
    QVector3D getModelCenter() const;

    bool parseMtlFile(const QString& mtlPath);

    bool handleFaceGroups();

    Qt3DRender::QGeometryRenderer* createGeometryRendererFromData(
        const QVector<float>& vertexData,
        const QVector<unsigned int>& indexData);

    QVector<MeshPart> m_meshParts;

private:

    // 当前正在使用的材质名
    QString m_currentMaterial;

    // 材质名 -> 材质数据
    QHash<QString, Material> m_materialMap;

    /**
     * @brief m_zipFilePath 解析的zip文件路径
     */
    QString m_zipFilePath;

    /**
     * @brief m_objFilePath 解析的obj文件路径
     */
    QString m_objFilePath;

    /**
     * @brief m_mtlFilePath 解析的mtl文件路径
     */
    QString m_mtlFilePath;

    /**
     * @brief m_positions 存储 "v" 行
     */
    QVector<QVector3D> m_positions;

    /**
     * @brief m_texCoords 存储 "vt" 行
     */
    QVector<QVector2D> m_texCoords;

    /**
     * @brief m_normals 存储 "vn" 行
     */
    QVector<QVector3D> m_normals;

    /**
     * @brief faces 存储 "f" 行，每个面是多个FaceIndex的集合
     */
    QVector<QVector<FaceIndex>> faces;

    // 替换原来的 faces
    QHash<QString, QVector<QVector<FaceIndex>>> m_faceGroups; // 材质名 -> 面列表




    // 将构建一个交错数组 (Interleaved Array) 来存储每个顶点的所有属性
    // 例如： [position_x, position_y, position_z, normal_x, normal_y, normal_z, tex_u, tex_v, ...]
    QVector<float> m_vertexData;
    QVector<unsigned int> m_indexData;

    /**
     * @brief totalMainProcessNum 模型解析主进度最大值
     */
    int m_totalMainProcessNum;

};

#endif // OBJPARSE_H
